package com.vision.sales.advancepayment.cl.ui;

import static com.vision.sales.cl.SalesServices.appliedAdvancePaymentSvc;

import java.util.Date;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.editor.client.SimpleBeanEditorDriver;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.text.shared.AbstractSafeHtmlRenderer;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiFactory;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.widget.core.client.Window;
import com.sencha.gxt.widget.core.client.button.TextButton;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.sencha.gxt.widget.core.client.form.DateField;
import com.sencha.gxt.widget.core.client.form.NumberField;
import com.sencha.gxt.widget.core.client.form.NumberPropertyEditor;
import com.sencha.gxt.widget.core.client.form.TextField;
import com.vision.core.cl.BaseModule;
import com.vision.core.cl.Callback;
import com.vision.core.cl.ui.UI;
import com.vision.sales.cl.SalesServices;
import com.vision.sales.cl.event.AppliedAdvancePaymentCreatedEvent;
import com.vision.sales.cl.resource.SalesResources;
import com.vision.sales.cl.ui.component.SalesInvoiceComboBox;
import com.vision.sales.cl.ui.component.SalesInvoiceComboBox.Templates;
import com.vision.sales.cm.db.data.AdvancePayment;
import com.vision.sales.cm.db.data.AppliedAdvancePayment;
import com.vision.sales.cm.db.data.SalesInvoice;

/**
 * 
 * @author Mark
 *
 */
public class ApplyAdvancePaymentWindow implements IsWidget, Editor<AppliedAdvancePayment> {
	
	interface Binder extends UiBinder<Widget, ApplyAdvancePaymentWindow> { }
	
	private static final Binder binder = GWT.create(Binder.class);
	
	private AdvancePayment advancePayment;
	
	@UiField Window window;
	@UiField VerticalLayoutContainer mainPanel;

	@Ignore @UiField TextField company;
	@Ignore @UiField TextField customer;
	@Ignore @UiField TextField advancePaymentNo;
	@Ignore @UiField NumberField<Double> balance;
	@UiField DateField dateApplied;
	@UiField SalesInvoiceComboBox salesInvoice;
	@Ignore @UiField NumberField<Double> salesInvoiceBalance;
	@UiField NumberField<Double> appliedAmount;
	
	@Ignore @UiField TextButton applyBtn;
	@Ignore @UiField TextButton cancelBtn;
	
	@UiField(provided = true) NumberFormat numberFormat = UI.amountFormat();
	@UiField(provided = true) NumberPropertyEditor<Double> doublePropertyEditor = UI.doubleEditor();
	
	interface AdvancePaymentDriver extends SimpleBeanEditorDriver<AppliedAdvancePayment, ApplyAdvancePaymentWindow> { }
	
	private AdvancePaymentDriver driver = GWT.create(AdvancePaymentDriver.class); // Used to bind the grid to the form editor
	
	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	public ApplyAdvancePaymentWindow(AdvancePayment advancePayment) {
		this.advancePayment = advancePayment;
	}
	
	@Override
	public Widget asWidget() {
		window = (Window) binder.createAndBindUi(this);
		window.getHeader().setIcon(SalesResources.INSTANCE.advancePayments());
		
		dateApplied.setPropertyEditor(UI.datePropertyEditor());
		dateApplied.setValue(new Date());
		
		driver.initialize(this);
		driver.edit( new AppliedAdvancePayment(this.advancePayment) );
		
		company.setValue(advancePayment.getCompany().getCode());
		customer.setValue(advancePayment.getCustomer().getCode());
		advancePaymentNo.setValue(advancePayment.getAdvancePaymentNo());
		balance.setValue(advancePayment.getBalance());
		
		loadData();
		
		return window;
	}
	
	// UiFactory Methods %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	@Ignore
	@UiFactory
	SalesInvoiceComboBox initializeSalesInvoiceCombo() {
		SalesInvoiceComboBox combo = new SalesInvoiceComboBox(new AbstractSafeHtmlRenderer<SalesInvoice>() {
			@Override
			public SafeHtml render(SalesInvoice invoice) {
				String date = UI.basicDateFormat(invoice.getDate());
				String gross = UI.AMOUNT_FORMAT.format(invoice.getGrossSales());
				String balance = UI.AMOUNT_FORMAT.format(invoice.getBalance());
				return Templates.INSTANCE.invoice(date, invoice.getGroupAndNo(), gross, balance);
			}
		});
		return combo;
	}
	
	// Listeners %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	@UiHandler("salesInvoice")
	void salesInvoiceChanged(SelectionEvent<SalesInvoice> e) {
		SalesInvoice invoice = e.getSelectedItem();
		if (invoice == null)
			return;
		salesInvoiceBalance.setValue(invoice.getBalance());
	}
	
	@UiHandler("applyBtn")
	void applyClicked(SelectEvent e) {
		AppliedAdvancePayment applied = driver.flush();
		if (driver.hasErrors())
			return;
		
		AdvancePayment payment = applied.getAdvancePayment();
		if (applied.getAppliedAmount() > payment.getBalance()) {
			UI.info("Input Error", "Amount to apply cannot be larger than the advance payment's balance.", null);
			return;
		}
		
		SalesInvoice invoice = applied.getSalesInvoice();
		if (applied.getAppliedAmount() > invoice.getBalance()) {
			UI.info("Input Error", "Amount to apply cannot be larger than the invoice's balance.", null);
			return;
		}
		
		UI.mask(window, "Applying advance payment...");
		appliedAdvancePaymentSvc().create(applied, new Callback<AppliedAdvancePayment>(window) {
			@Override
			protected void handleSuccess(AppliedAdvancePayment result) {
				window.hide(applyBtn);
				BaseModule.fireEvent(new AppliedAdvancePaymentCreatedEvent(result));
			}
		});
	}
	
	@UiHandler("cancelBtn")
	void cancelClicked(SelectEvent e) {
		window.hide(cancelBtn);
	}
	
	// Logic %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

	public void loadData() {
		UI.mask(salesInvoice, "Loading sales invoices...");
		SalesServices.salesInvoiceSvc().getSalesInvoicesForAdvancePayment(advancePayment.getId(),
			new Callback<List<SalesInvoice>>(salesInvoice) {
				@Override
				protected void handleSuccess(List<SalesInvoice> result) {
					salesInvoice.getStore().clear();
					salesInvoice.getStore().addAll(result);
				}
			}
		);
	}
	
}
